#include <cstdio>
#include <cstdlib>
#include <windows.h>

#include "sqstack.h"

typedef struct {
    int year;
    int month;
    int day;
} Production;

Production productions[] = {
    {2024, 4, 2},
    {2024, 5, 30},
    {2025, 3, 5},
    {2025, 1, 1},
    {2023, 12, 31}
};


void setup() {
    // 设置控制台代码页为UTF-8
    SetConsoleOutputCP(CP_UTF8);
    // 设置控制台输入代码页为UTF-8
    SetConsoleCP(CP_UTF8);
    setvbuf(stdout, NULL, _IONBF, 0); // 设置为无缓冲模式
}

Status Production_Print(SqStack S) {
    int first = 1;
    printf("Bottom-");
    SElemType *temp = S.base;
    while (temp != S.top) {
        if (first) {
            first = 0;
        } else {
            printf("->");
        }
        Production p = productions[*temp];
        printf("|%04d-%02d-%02d|", p.year, p.month, p.day);
        temp++;
    }
    printf("-Top");
    return OK;
}

Status Production_Early(Production p1, Production p2) {
    if (p1.year < p2.year) {
        return TRUE;
    }

    if (p1.year > p2.year) {
        return FALSE;
    }

    if (p1.month < p2.month) {
        return TRUE;
    }

    if (p1.month > p2.month) {
        return FALSE;
    }

    if (p1.day < p2.day) {
        return TRUE;
    }

    if (p1.day > p2.day) {
        return FALSE;
    }
}

int main() {
    setup();

    printf("测试栈的初始化、插入、弹出、获得栈顶的值、判断是否为空以及销毁。\n");

    SqStack S;

    // 初始化
    SqStack_Init(S);

    if (SqStack_StackEmpty(S)) {
        printf("现在栈是空的！\n");
    }

    printf("准备测试入栈。\n");

    int data[] = {1, 1, 4, 5, 1, 4};

    // 入栈
    for (int i = 0; i < 6; i++) {
        if (SqStack_Push(S, data[i])) {
            printf("元素 %d 入栈，目前栈是：\n");
            SqStack_Display(S);
            printf("\n");
        } else {
            printf("元素 %d 入栈失败！\n");
        }
    }

    // 出栈
    printf("准备测试出栈。\n");
    for (int i = 0; i < 2; i++) {
        SElemType e;
        if (SqStack_Pop(S, e)) {
            printf("元素 %d 出栈，目前栈是：\n", e);
            SqStack_Display(S);
            printf("\n");
        } else {
            printf("元素出栈失败！\n");
        }
    }

    if (!SqStack_StackEmpty(S)) {
        printf("现在栈不是空的！\n");
    }

    SElemType e;
    SqStack_GetTop(S, e);
    printf("栈顶元素是 %d 。\n", e);


    SqStack_Clear(S);
    printf("栈清空成功！\n");


    printf("现在测试生产日期排序：\n");

    for (int i = 0; i < 5; i++) {
        if (SqStack_Push(S, i)) {
            printf("商品 %d 入栈，目前栈是：\n");
            Production_Print(S);
            printf("\n");
        } else {
            printf("商品 %d 入栈失败！\n");
        }
    }

    SqStack TS;

    // 创建临时排序栈
    SqStack_Init(TS);

    while (!SqStack_StackEmpty(S)) {
        SElemType e, top;
        SqStack_Pop(S, e);

        if (SqStack_GetTop(TS, top)) {
            while (!Production_Early(productions[top], productions[e])) {
                SqStack_Pop(TS, top);
                SqStack_Push(S, top);
                if (!SqStack_GetTop(TS, top)) {
                    break;
                }
            }
        }

        SqStack_Push(TS, e);
    }

    while (!SqStack_StackEmpty(TS)) {
        SElemType e;
        SqStack_Pop(TS, e);
        SqStack_Push(S, e);
    }

    printf("排好序的商品栈：\n");
    Production_Print(S);
    printf("\n");

    // 删除临时栈
    SqStack_Destroy(TS);

    // 清空栈
    SqStack_Clear(S);

    printf("使用栈来判断回文，由于编码限制，请确保只输入英文和数字（不超过100个字符）：\n");

    char strings[101];
    scanf("%s", &strings);
    int length = (int) strlen(strings);

    // 将每个字符压入栈
    int i = 0;
    for (i = 0; i < length / 2; i++) {
        SqStack_Push(S, (SElemType) strings[i]);
    }

    // 这个时候栈里面就压了一半的字符，对于奇数个字符把 i 向后移动一个位置
    if (length % 2) {
        i++;
    }

    int is_hw = true;
    while (!SqStack_StackEmpty(S)) {
        SElemType e;
        SqStack_Pop(S, e);
        if ((char) e != strings[i]) {
            is_hw = false;
            break;
        }
        i++; // 移动一位字符
    }

    printf(is_hw ? "此字符序列构成回文！\n" : "此字符序列不构成回文！\n");

    printf("现在测试堆栈操作的合法性，输出测试次数：");

    int times = 0;

    getchar();
    scanf("%d", &times);
    getchar();

    for (int _ = 0; _ < times; _++) {
        printf("请输入大写 S（入栈）和大写 X（出栈）组成的序列：\n");
        SqStack_Clear(S);

        int c, success = 1;
        SElemType t;
        while ((c = getchar()) != '\n') {
            if (c == 'S') {
                if (!SqStack_Push(S, 0)) {
                    success = 0;
                    break;
                }
            } else {
                if (!SqStack_Pop(S, t)) {
                    success = 0;
                    break;
                }
            }
        }


        if (!success) {
            printf("此序列无效！\n");
            // 清空缓存
            while ((c = getchar()) != '\n');
        } else {
            printf("此序列有效！\n");
        }
    }

    system("pause");
    return 0;
}
